/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ie.tcd.cs.railtickets.server.net;

import ie.tcd.cs.railtickets.commons.dto.BookRequestDTO;
import ie.tcd.cs.railtickets.commons.dto.CancelRequestDTO;
import ie.tcd.cs.railtickets.commons.dto.PriceInfoRequestDTO;
import static ie.tcd.cs.railtickets.commons.util.NetUtil.simpleSendObject;
import java.io.IOException;
import java.net.Socket;
import ie.tcd.cs.railtickets.server.service.GraphService;
import ie.tcd.cs.railtickets.server.service.TicketService;
import ie.tcd.cs.railtickets.server.service.ServiceFactory;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Wenbo Sun
 */
public class OperationHandler extends Thread {

    private Socket socket;
    private TicketService ticketService;
    private static final Log log = LogFactory.getLog(OperationHandler.class);

    public OperationHandler() {
    }

    
    public OperationHandler(Socket socket) {
        super();
        this.socket = socket;
        ticketService = ServiceFactory.createTicketService();
    }

    public Object handleRequest(String ipAddr) {
        InputStream is = null;
        Object result = null;

        try {
            is = socket.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
            Object request = ois.readObject();
            if (request instanceof BookRequestDTO) {
                log.debug("accept book request ...");
                result = handleBookRequest((BookRequestDTO) request, ipAddr);
            } else if (request instanceof PriceInfoRequestDTO) {
                log.debug("accept search request ...");
                result = this.handlePriceInfoRequest((PriceInfoRequestDTO) request);
                
            } else if (request instanceof CancelRequestDTO) {
                log.debug("accept cancel request ...");
                result = this.handleCancelRequest((CancelRequestDTO) request, ipAddr);

            }else {
                log.debug("accept update graph request ...");
                result = this.handleGraphRequest();
            }
        } catch (IOException ex) {
            log.error("get input stream failed", ex);
        } finally {
            return result;
        }
    }

    public Object handleBookRequest(BookRequestDTO brDTO, String ipAddr) {
        long timeId = brDTO.getTimeId();
        int sum = brDTO.getSum();
        Date travelDate = brDTO.getTravelDate();
        return ticketService.bookTickets(timeId, travelDate, sum, ipAddr);
    }

    public Object handlePriceInfoRequest(PriceInfoRequestDTO piDTO) {
        String source = piDTO.getSource();
        String destination = piDTO.getDestination();
        Date travelDate = piDTO.getTravelDate();
        return ticketService.getPriceInfos(source, destination, travelDate);
    }

    public Object handleGraphRequest() {
        GraphService graphService = ServiceFactory.createGraphService();
        return graphService.getRailsGraph();
    }

    public boolean checkIP() {
        String ad = socket.getInetAddress().getHostAddress();
        log.debug("request source address: " + ad);
        boolean bool = ticketService.checkAgentExist(ad);

        if(bool)
            return true;
        return false;
    }

    @Override
    public void run() {
        super.run();
        if (!checkIP()) {
            try {
                socket.close();
            } catch (IOException ex) {
                log.error("close socket failed", ex);
            }
        } else {
            try {
                Object o = handleRequest(socket.getInetAddress().getHostAddress());
                simpleSendObject(socket, o);
            } catch (IOException ex) {
                log.error("send object back failed!", ex);
            } catch (ClassNotFoundException ex) {
                log.error("send object back failed!", ex);
            }
        }
    }

    private Object handleCancelRequest(CancelRequestDTO cancelRequestDTO, String ipAddr) {
        return ticketService.cancelTicket(cancelRequestDTO.getTicketNo(), ipAddr);
    }
}
